As processors have become faster, main memory access has become the bottleneck to overall increased performance. Therefore, in order to improve performance, memory caching schemes have been adopted to lessen the effect of the main memory bottleneck. The PENTIUM processor employs one such memory caching scheme that uses a very fast primary cache and a fast secondary cache. When the processor needs to read data from memory, the processor first checks the primary cache to locate the data. If the requested data is not found in the primary cache, then the secondary cache is checked, which has a slower access time than the primary cache, but is still much faster than main memory. If the data is located in the secondary cache, the data is returned to the processor and the line ("cache line") of the secondary cache that stored the data is copied into the primary cache. Data is stored in both the primary cache and the secondary cache in terms of 32-byte cache lines. The primary cache is 8 KB in size, so it can store 256 cache lines. The secondary cache is typically 256 KB to 512 KB, so it can store between 8,192 to 16,384 cache lines.
If after checking the secondary cache the data is still not found, main memory is accessed which has a significantly slower access time than the secondary cache. When main memory is accessed, not only the requested data, but an entire memory line of 32bytes is returned. The processor receives the requested data, and both the primary and secondary caches receive the entire 32-byte memory line. The 32-byte memory line is stored in the caches in the hope that the next time the processor needs to read data from memory, the data will be found within this cache line. To put the costs in perspective, it takes 1 processor cycle to access the primary cache, 4-12 processor cycles to access the secondary cache, and typically 50 processor cycles to access main memory. Therefore, the primary cache could be searched perhaps 50 times in the time that it takes to access main memory once. The PENTIUM processor's caching scheme is described in greater detail in Anderson and Shanley, Pentium Processor System Architecture, at 35-60, 2.sup.nd ed., Addison-Wesley (1995), which is hereby incorporated by reference.
Hashing mechanisms play an important role in many computer systems. Conventional hashing mechanisms utilize a data structure known as a hash table to provide direct access to stored data. One such example of a conventional hashing mechanism 100 is depicted in FIG. 1. The hashing mechanism 100 comprises a key 102, a hash function 104, a hash index 106, and a hash table 108. The hash table 108 contains a number of hash buckets 110-130, and each hash bucket contains data, such as a record, with one of the fields of the record acting as the key 102. In order to access the hash table 108, the key 102 is input into a hash function 104 which yields an index 106 (or hash address) that refers to a specific hash bucket (e.g, 114). Within the hash bucket 114 is the data that matches the key. Hash tables are useful because they provide direct access to data by mapping a large range of key values into a smaller range of indexes. In this manner, for example, if a key of eight digits were utilized having a range of key values from 0 to 99,999,999 and if less than ten values are ever used, a hashing mechanism can be used to hash the key into an index of one digit to refer to a hash table containing ten buckets. Therefore, instead of using a hash table having one-hundred-million hash buckets where only a very limited number of the buckets are ever used, a hash table of only ten buckets can be used to more efficiently use system resources, but still provide direct access to the data.
The function "h" 104 maps each key value onto exactly one index, and therefore, whenever the same key value is used more than once, the same index 106 into the hash table 108 is generated. Sometimes, however, when attempting to store data in the hash table 108, more than one key value will hash to the same index 106. In this situation, a "collision" has occurred. When a collision occurs, the data must be stored in the hash bucket indicated by the index and therefore more than one record will be stored in this hash bucket. Hash bucket 118 depicts the state of a hash bucket after a collision has occurred and more than one record is stored in the hash bucket. In hash bucket 118, one record of data "data3" is linked to a second record of data "data4." As more collisions occur, the hash buckets become more populated and thus the benefits of a hash table start to diminish because each record within the hash bucket is no longer directly accessible. Instead, after hashing the key value into an index, the index refers to a hash bucket that contains a number of records linked together and the hash bucket must then be searched to determine the correct record, which is costly in terms of processing time. Therefore, conventional hashing systems are designed to avoid collisions.
Because a hash table provides direct access to the data that it stores, hash tables are an important part of many existing computer systems. It is thus desirable to improve the performance of hash mechanisms. However, conventional hash mechanisms have failed to take advantage of the caching architecture of today's processors.